1use super::*;
3
4pub struct Strip<'a> {
34 remote: &'a VoicemeeterRemote,
35 strip_index: ZIndex,
36}
37
38impl<'a> Strip<'a> {
39 #[doc(hidden)]
40 pub fn new(remote: &'a VoicemeeterRemote, strip_index: ZIndex) -> Self {
41 Strip {
42 remote,
43 strip_index,
44 }
45 }
46 pub fn param(&self, dot: impl Display) -> Cow<'static, ParameterNameRef> {
48 Cow::Owned(format!("{STRIP}[{}].{}", self.strip_index, dot).into())
50 }
51 #[rustfmt::skip]
53 pub fn is_physical(&self) -> bool {
54 matches!((self.remote.program, self.strip_index.0),
55 | (VoicemeeterApplication::Voicemeeter, 0..=1)
56 | (VoicemeeterApplication::VoicemeeterBanana, 0..=2)
57 | (VoicemeeterApplication::VoicemeeterPotato, 0..=4)
58 | (VoicemeeterApplication::PotatoX64Bits, 0..=4)
59 )
60 }
61
62 pub fn is_virtual(&self) -> bool {
64 !(self.is_physical() || matches!(self.remote.program, VoicemeeterApplication::Other))
65 }
66
67 pub fn mono(&self) -> BoolParameter<'_> {
69 BoolParameter::new(self.param("Mono"), self.remote)
70 }
71
72 pub fn mute(&self) -> BoolParameter<'_> {
74 BoolParameter::new(self.param("Mute"), self.remote)
75 }
76
77 pub fn solo(&self) -> BoolParameter<'_> {
79 BoolParameter::new(self.param("Solo"), self.remote)
80 }
81
82 pub fn mute_center(&self) -> BoolParameter<'_> {
85 BoolParameter::new(self.param("MC"), self.remote)
86 }
87
88 pub fn gain(&self) -> FloatParameter<'_> {
90 FloatParameter::new(self.param("Gain"), self.remote, -60.0..=12.0)
91 }
92
93 pub fn gain_layer(&self, layer: impl Into<ZIndex>) -> FloatParameter<'_> {
96 let layer = layer.into();
97 let name = self.param(format!("GainLayer[{layer}]"));
98 FloatParameter::new(name, self.remote, -60.0..=12.0)
99 }
100
101 pub fn pan_x(&self) -> FloatParameter<'_> {
104 FloatParameter::new(self.param("Pan_x"), self.remote, -0.5..=0.5)
105 }
106
107 pub fn pan_y(&self) -> FloatParameter<'_> {
109 FloatParameter::new_unranged(self.param("Pan_y"), self.remote)
111 }
112
113 pub fn color_x(&self) -> Result<FloatParameter<'_>, InvalidTypeError> {
115 if self.is_virtual() {
116 Err(InvalidTypeError::ExpectedPhysical {
117 name: STRIP,
118 strip_index: self.strip_index,
119 parameter: "Color_x".to_string(),
120 })
121 } else {
122 Ok(FloatParameter::new(
123 self.param("Color_x"),
124 self.remote,
125 -0.5..=0.5,
126 ))
127 }
128 }
129
130 pub fn color_y(&self) -> Result<FloatParameter<'_>, InvalidTypeError> {
132 if self.is_virtual() {
133 Err(InvalidTypeError::ExpectedPhysical {
134 name: STRIP,
135 strip_index: self.strip_index,
136 parameter: "Color_y".to_string(),
137 })
138 } else {
139 Ok(FloatParameter::new(
140 self.param("Color_y"),
141 self.remote,
142 0.0..=1.0,
143 ))
144 }
145 }
146
147 pub fn fx_x(&self) -> Result<FloatParameter<'_>, InvalidTypeError> {
149 if self.is_virtual() {
150 Err(InvalidTypeError::ExpectedPhysical {
151 name: STRIP,
152 strip_index: self.strip_index,
153 parameter: "fx_x".to_string(),
154 })
155 } else {
156 Ok(FloatParameter::new(
157 self.param("fx_x"),
158 self.remote,
159 -0.5..=0.5,
160 ))
161 }
162 }
163
164 pub fn fx_y(&self) -> Result<FloatParameter<'_>, InvalidTypeError> {
166 if self.is_virtual() {
167 Err(InvalidTypeError::ExpectedPhysical {
168 name: STRIP,
169 strip_index: self.strip_index,
170 parameter: "fx_y".to_string(),
171 })
172 } else {
173 Ok(FloatParameter::new(
174 self.param("fx_y"),
175 self.remote,
176 0.0..=1.0,
177 ))
178 }
179 }
180
181 pub fn audability(&self) -> FloatParameter<'_> {
183 FloatParameter::new(self.param("Audability"), self.remote, 0.0..=10.0)
184 }
185 pub fn comp(&self) -> FloatParameter<'_> {
190 FloatParameter::new(self.param("Comp"), self.remote, 0.0..=10.0)
191 }
192
193 pub fn comp_detailed(&self) -> Result<StripCompressor<'_>, ParameterError> {
197 const VALID: &[VoicemeeterApplication] = &[
198 VoicemeeterApplication::VoicemeeterPotato,
199 VoicemeeterApplication::PotatoX64Bits,
200 ];
201 if VALID.contains(&self.remote.program) {
202 if self.is_physical() {
203 Ok(StripCompressor::new(self.remote, self.strip_index))
204 } else {
205 Err(InvalidTypeError::ExpectedPhysical {
206 name: STRIP,
207 strip_index: self.strip_index,
208 parameter: "Comp".to_string(),
209 }
210 .into())
211 }
212 } else {
213 Err(InvalidVoicemeeterVersion {
214 expected: VALID,
215 found: self.remote.program,
216 parameter: self.param("Comp").to_string(),
217 }
218 .into())
219 }
220 }
221
222 pub fn gate(&self) -> FloatParameter<'_> {
226 FloatParameter::new(self.param("Gate"), self.remote, 0.0..=10.0)
227 }
228
229 pub fn gate_detailed(&self) -> Result<StripGate<'_>, ParameterError> {
233 const VALID: &[VoicemeeterApplication] = &[
234 VoicemeeterApplication::VoicemeeterPotato,
235 VoicemeeterApplication::PotatoX64Bits,
236 ];
237
238 if VALID.contains(&self.remote.program) {
239 if self.is_physical() {
240 Ok(StripGate::new(self.remote, self.strip_index))
241 } else {
242 Err(InvalidTypeError::ExpectedPhysical {
243 name: STRIP,
244 strip_index: self.strip_index,
245 parameter: "Gate".to_string(),
246 }
247 .into())
248 }
249 } else {
250 Err(InvalidVoicemeeterVersion {
251 expected: VALID,
252 found: self.remote.program,
253 parameter: self.param("Gate").to_string(),
254 }
255 .into())
256 }
257 }
258
259 pub fn denoiser(&self) -> Result<FloatParameter<'_>, ParameterError> {
261 const VALID: &[VoicemeeterApplication] = &[
262 VoicemeeterApplication::VoicemeeterPotato,
263 VoicemeeterApplication::PotatoX64Bits,
264 ];
265
266 if VALID.contains(&self.remote.program) {
267 if self.is_physical() {
268 Ok(FloatParameter::new(
269 self.param("Denoiser"),
270 self.remote,
271 0.0..10.0,
272 ))
273 } else {
274 Err(InvalidTypeError::ExpectedPhysical {
275 name: STRIP,
276 strip_index: self.strip_index,
277 parameter: "Gate".to_string(),
278 }
279 .into())
280 }
281 } else {
282 Err(InvalidVoicemeeterVersion {
283 expected: VALID,
284 found: self.remote.program,
285 parameter: self.param("Gate").to_string(),
286 }
287 .into())
288 }
289 }
290
291 pub fn karaoke(&self) -> IntParameter<'_> {
293 IntParameter::new(self.param("Karaoke"), self.remote, 0..=4)
294 }
295
296 pub fn limit(&self) -> IntParameter<'_> {
298 IntParameter::new(self.param("Limit"), self.remote, -40..=12)
299 }
300
301 pub fn eq_gain1(&self) -> Result<FloatParameter<'_>, InvalidTypeError> {
303 if self.is_physical() {
304 Err(InvalidTypeError::ExpectedPhysical {
305 name: STRIP,
306 strip_index: self.strip_index,
307 parameter: "EQGain1".to_string(),
308 })
309 } else {
310 Ok(FloatParameter::new(
311 self.param("EQGain1"),
312 self.remote,
313 -12.0..=12.0,
314 ))
315 }
316 }
317
318 pub fn eq_gain2(&self) -> Result<FloatParameter<'_>, InvalidTypeError> {
320 if self.is_physical() {
321 Err(InvalidTypeError::ExpectedPhysical {
322 name: STRIP,
323 strip_index: self.strip_index,
324 parameter: "EQGain2".to_string(),
325 })
326 } else {
327 Ok(FloatParameter::new(
328 self.param("EQGain2"),
329 self.remote,
330 -12.0..=12.0,
331 ))
332 }
333 }
334
335 pub fn eq_gain3(&self) -> Result<FloatParameter<'_>, InvalidTypeError> {
337 if self.is_physical() {
338 Err(InvalidTypeError::ExpectedPhysical {
339 name: STRIP,
340 strip_index: self.strip_index,
341 parameter: "EQGain3".to_string(),
342 })
343 } else {
344 Ok(FloatParameter::new(
345 self.param("EQGain3"),
346 self.remote,
347 -12.0..=12.0,
348 ))
349 }
350 }
351
352 pub fn label(&self) -> StringParameter<'_> {
354 StringParameter::new(self.param("Label"), self.remote)
355 }
356
357 pub fn a1(&self) -> BoolParameter<'_> {
359 BoolParameter::new(self.param("A1"), self.remote)
360 }
361 pub fn a2(&self) -> BoolParameter<'_> {
363 BoolParameter::new(self.param("A2"), self.remote)
364 }
365 pub fn a3(&self) -> BoolParameter<'_> {
367 BoolParameter::new(self.param("A3"), self.remote)
368 }
369 pub fn a4(&self) -> BoolParameter<'_> {
371 BoolParameter::new(self.param("A4"), self.remote)
372 }
373 pub fn a5(&self) -> BoolParameter<'_> {
375 BoolParameter::new(self.param("A5"), self.remote)
376 }
377 pub fn b1(&self) -> BoolParameter<'_> {
379 BoolParameter::new(self.param("B1"), self.remote)
380 }
381 pub fn b2(&self) -> BoolParameter<'_> {
383 BoolParameter::new(self.param("B2"), self.remote)
384 }
385 pub fn b3(&self) -> BoolParameter<'_> {
387 BoolParameter::new(self.param("B3"), self.remote)
388 }
389 pub fn eq_on(&self) -> BoolParameter<'_> {
391 BoolParameter::new(self.param("EQ.on"), self.remote)
392 }
393 pub fn eq_ab(&self) -> BoolParameter<'_> {
395 BoolParameter::new(self.param("EQ.AB"), self.remote)
396 }
397 pub fn eq(&self, channel: usize) -> Result<EqChannelParameter<'_>, ParameterError> {
399 const VALID: &[VoicemeeterApplication] = &[
400 VoicemeeterApplication::VoicemeeterPotato,
401 VoicemeeterApplication::PotatoX64Bits,
402 ];
403 let eq = EqChannelParameter::new_strip(self.remote, self.strip_index, channel);
404 if VALID.contains(&self.remote.program) {
405 if self.is_physical() {
406 Ok(eq)
407 } else {
408 Err(InvalidTypeError::ExpectedPhysical {
409 name: STRIP,
410 strip_index: self.strip_index,
411 parameter: eq.name().to_string(),
412 }
413 .into())
414 }
415 } else {
416 Err(InvalidVoicemeeterVersion {
417 expected: VALID,
418 found: self.remote.program,
419 parameter: eq.name().to_string(),
420 }
421 .into())
422 }
423 }
424 pub fn fade_to(&self) -> TupleParameter<'_, i32, usize> {
426 TupleParameter::new(self.param("FadeTo"), self.remote)
427 }
428 pub fn fade_by(&self) -> TupleParameter<'_, i32, usize> {
430 TupleParameter::new(self.param("FadeBy"), self.remote)
431 }
432 pub fn reverb(&self) -> FloatParameter<'_> {
434 FloatParameter::new(self.param("Reverb"), self.remote, 0.0..=10.0)
435 }
436 pub fn delay(&self) -> FloatParameter<'_> {
438 FloatParameter::new(self.param("Delay"), self.remote, 0.0..=10.0)
439 }
440 pub fn fx1(&self) -> FloatParameter<'_> {
442 FloatParameter::new(self.param("Fx1"), self.remote, 0.0..=10.0)
443 }
444 pub fn fx2(&self) -> FloatParameter<'_> {
446 FloatParameter::new(self.param("Fx2"), self.remote, 0.0..=10.0)
447 }
448 pub fn post_reverb(&self) -> BoolParameter<'_> {
450 BoolParameter::new(self.param("PostReverb"), self.remote)
451 }
452 pub fn post_delay(&self) -> BoolParameter<'_> {
454 BoolParameter::new(self.param("PostDelay"), self.remote)
455 }
456 pub fn post_fx1(&self) -> BoolParameter<'_> {
458 BoolParameter::new(self.param("PostFx1"), self.remote)
459 }
460 pub fn post_fx2(&self) -> BoolParameter<'_> {
462 BoolParameter::new(self.param("PostFx2"), self.remote)
463 }
464
465 pub fn app_gain_indexed(&self, application_index: ZIndex) -> FloatParameter<'_, true, false> {
467 FloatParameter::new(
468 self.param(format!("App[{application_index}].Gain")),
469 self.remote,
470 0.0..=1.0,
471 )
472 }
473
474 pub fn app_mute_indexed(&self, application_index: ZIndex) -> BoolParameter<'_, true, false> {
476 BoolParameter::new(
477 self.param(format!("App[{application_index}].Mute")),
478 self.remote,
479 )
480 }
481
482 pub fn app_gain(&self) -> TupleParameter<'_, String, f32, true, false> {
484 TupleParameter::new(self.param("AppGain"), self.remote)
485 }
486
487 pub fn app_mute(&self) -> TupleParameter<'_, String, bool, true, false> {
489 TupleParameter::new(self.param("AppMute"), self.remote)
490 }
491
492 pub fn device(&self) -> Result<StripDevice<'a>, InvalidTypeError> {
494 if self.is_virtual() {
495 Err(InvalidTypeError::ExpectedPhysical {
496 name: STRIP,
497 strip_index: self.strip_index,
498 parameter: "device".to_string(),
499 })
500 } else {
501 Ok(StripDevice::new(self.remote, self.strip_index))
502 }
503 }
504
505 pub fn vaio(&self) -> BoolParameter<'_> {
509 BoolParameter::new(self.param("VAIO"), self.remote)
510 }
511}
512
513pub struct StripDevice<'a> {
515 remote: &'a VoicemeeterRemote,
516 strip_index: ZIndex,
517}
518
519impl<'a> StripDevice<'a> {
520 fn new(remote: &'a VoicemeeterRemote, strip_index: ZIndex) -> Self {
521 Self {
522 remote,
523 strip_index,
524 }
525 }
526
527 pub fn param(&self, dot: impl ToString) -> Cow<'static, ParameterNameRef> {
529 Cow::Owned(format!("{STRIP}[{}].device.{}", self.strip_index, dot.to_string()).into())
530 }
531
532 pub fn name(&self) -> StringParameter<'a, false, true> {
534 StringParameter::new(self.param("name"), self.remote)
535 }
536
537 pub fn sr(&self) -> IntParameter<'a, false, true> {
539 IntParameter::new_unranged(self.param("sr"), self.remote)
540 }
541 pub fn wdm(&self) -> StringParameter<'a, true, false> {
543 StringParameter::new(self.param("wdm"), self.remote)
544 }
545 pub fn ks(&self) -> StringParameter<'a, true, false> {
547 StringParameter::new(self.param("ks"), self.remote)
548 }
549 pub fn mme(&self) -> StringParameter<'a, true, false> {
551 StringParameter::new(self.param("mme"), self.remote)
552 }
553 pub fn asio(&self) -> StringParameter<'a, true, false> {
555 StringParameter::new(self.param("asio"), self.remote)
556 }
557}
558
559pub struct StripCompressor<'a> {
563 remote: &'a VoicemeeterRemote,
564 strip_index: ZIndex,
565}
566
567impl<'a> StripCompressor<'a> {
568 fn new(remote: &'a VoicemeeterRemote, strip_index: ZIndex) -> Self {
569 Self {
570 remote,
571 strip_index,
572 }
573 }
574
575 pub fn param(&self, dot: impl ToString) -> Cow<'static, ParameterNameRef> {
577 Cow::Owned(format!("{STRIP}[{}].comp.{}", self.strip_index, dot.to_string()).into())
578 }
579
580 pub fn gain_in(&self) -> FloatParameter<'a, true, true> {
584 FloatParameter::new(self.param("GainIn"), self.remote, -24.0..24.0)
585 }
586 pub fn ratio(&self) -> FloatParameter<'a, true, true> {
590 FloatParameter::new(self.param("Ratio"), self.remote, 1.0..8.0)
591 }
592 pub fn threshold(&self) -> FloatParameter<'a, true, true> {
597 FloatParameter::new(self.param("Threshold"), self.remote, -40.0..-3.0)
598 }
599 pub fn attack(&self) -> FloatParameter<'a, true, true> {
604 FloatParameter::new(self.param("Attack"), self.remote, 0.0..200.0)
605 }
606 pub fn release(&self) -> FloatParameter<'a, true, true> {
610 FloatParameter::new(self.param("Release"), self.remote, 0.0..5000.0)
611 }
612 pub fn knee(&self) -> FloatParameter<'a, true, true> {
617 FloatParameter::new(self.param("Knee"), self.remote, 0.0..1.0)
618 }
619 pub fn gain_out(&self) -> FloatParameter<'a, true, true> {
623 FloatParameter::new(self.param("GainOut"), self.remote, -24.0..24.0)
624 }
625 pub fn make_up(&self) -> BoolParameter<'a, true, true> {
630 BoolParameter::new(self.param("MakeUp"), self.remote)
631 }
632}
633
634pub struct StripGate<'a> {
638 remote: &'a VoicemeeterRemote,
639 strip_index: ZIndex,
640}
641
642impl<'a> StripGate<'a> {
643 fn new(remote: &'a VoicemeeterRemote, strip_index: ZIndex) -> Self {
644 Self {
645 remote,
646 strip_index,
647 }
648 }
649
650 pub fn param(&self, dot: impl ToString) -> Cow<'static, ParameterNameRef> {
652 Cow::Owned(format!("{STRIP}[{}].Gate.{}", self.strip_index, dot.to_string()).into())
653 }
654
655 pub fn threshold(&self) -> FloatParameter<'a, true, true> {
660 FloatParameter::new(self.param("Threshold"), self.remote, -60.0..-10.0)
661 }
662 pub fn damping(&self) -> FloatParameter<'a, true, true> {
668 FloatParameter::new(self.param("Damping"), self.remote, -60.0..-10.0)
669 }
670 pub fn bp_sidechain(&self) -> FloatParameter<'a, true, true> {
677 FloatParameter::new(self.param("BPSidechain"), self.remote, 100.0..=4000.0)
678 }
679 pub fn attack(&self) -> FloatParameter<'a, true, true> {
683 FloatParameter::new(self.param("Attack"), self.remote, 0.0..=1000.0)
684 }
685 pub fn hold(&self) -> FloatParameter<'a, true, true> {
690 FloatParameter::new(self.param("Hold"), self.remote, 0.0..=5000.0)
691 }
692 pub fn release(&self) -> FloatParameter<'a, true, true> {
697 FloatParameter::new(self.param("Release"), self.remote, 0.0..=5000.0)
698 }
699}